home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1995 June
/
MacFormat 25.iso
/
Shareware City
/
Developers
/
OutOfPhase1.1 Source
/
OutOfPhase Folder
/
SampleTestPlay.c
< prev
next >
Wrap
Text File
|
1994-08-23
|
10KB
|
365 lines
/* SampleTestPlay.c */
/*****************************************************************************/
/* */
/* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
/* Copyright (C) 1994 Thomas R. Lawrence */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
/* */
/*****************************************************************************/
#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"
#include "SampleTestPlay.h"
#include "SoundOutput.h"
#include "Memory.h"
#include "SampleWindow.h"
#include "SampleConsts.h"
#include "FixedPoint.h"
#define FRAMESPERBUFFER (8192)
#define MAXBUFFERS (3)
#define INITIALBUFFERS (MAXBUFFERS)
#define SIXTEENBITSHIFTFACTOR (10)
#define EIGHTBITSHIFTFACTOR (18)
typedef enum
{
eNoPlay EXECUTE(= -18481),
eLoopPlay,
eNoLoopPlay,
eWaiting
} InternalStates;
static InternalStates State = eNoPlay;
static SampleTestErrors ErrorOccurred;
static SampleWindowRec* Window;
static largefixedsigned* Data;
static long LoopStart;
static long LoopEnd;
static long CurrentIndex;
static NumBitsType NumBits;
static NumChannelsType NumChannels;
static long EndOfChannel;
static MyBoolean DoingLoop;
MyBoolean SampleTestPlayInProgress(void)
{
return State != eNoPlay;
}
void SampleTestPlayCallback(SampleWindowRec* TheWindow, MyBoolean IgnoreMe)
{
void* Buffer;
long Scan;
long LocalIndex;
long LocalEnd;
largefixedsigned* LocalData;
long Limit;
if (State == eNoPlay)
{
SoundOutputStereo StereoRequest;
SoundOutputNumBits BitsRequest;
State = eLoopPlay;
ErrorOccurred = eSampleTestNoError;
Window = TheWindow;
Data = SampleWindowGetRawFixedPointData(TheWindow);
if (Data == NIL)
{
ErrorOccurred = eSampleTestNoSample;
return;
}
SampleWindowFinalizeCurrentEdit(TheWindow);
LoopStart = SampleWindowGetLoopStart(TheWindow);
LoopEnd = SampleWindowGetLoopEnd(TheWindow);
if (LoopEnd == LoopStart)
{
State = eNoLoopPlay;
}
CurrentIndex = 0;
NumBits = SampleWindowGetNumBits(TheWindow);
NumChannels = SampleWindowGetNumChannels(TheWindow);
if (NumChannels == eSampleStereo)
{
StereoRequest = eStereo;
}
else
{
StereoRequest = eMono;
}
if (NumBits == eSample16bit)
{
BitsRequest = e16bit;
}
else
{
BitsRequest = e8bit;
}
if (!OpenSoundChannel(SampleWindowGetSamplingRate(TheWindow),
StereoRequest,BitsRequest,FRAMESPERBUFFER,MAXBUFFERS,INITIALBUFFERS))
{
ErrorOccurred = eSampleTestCouldntOpenChannel;
return;
}
DoingLoop = True;
EndOfChannel = PtrSize((char*)Data) / sizeof(largefixedsigned);
if (NumChannels == eSampleStereo)
{
EndOfChannel = EndOfChannel / 2;
}
}
if (State == eWaiting)
{
return;
}
if (ErrorOccurred != eSampleTestNoError)
{
return;
}
ERROR(Window != TheWindow,PRERR(ForceAbort,
"SampleTestPlayCallback: window pointers are different"));
/* set up local variable values */
Buffer = CheckOutSoundBuffer();
if (Buffer == NIL)
{
return;
}
Scan = 0;
LocalIndex = CurrentIndex;
LocalData = Data;
Limit = FRAMESPERBUFFER;
/* use one of the 8 synthesis techniques */
if (State == eNoLoopPlay)
{
LocalEnd = EndOfChannel; /* for no loop, the end is the real end */
if (NumChannels == eSampleStereo)
{
if (NumBits == eSample16bit)
{
/* stereo, 16-bit, no loop */
PRNGCHK(Buffer,Buffer,sizeof(short) * Limit * 2);
while (Scan < Limit)
{
if (LocalIndex >= LocalEnd)
{
goto AllDonePoint;
}
((signed short*)Buffer)[Scan * 2 + 0]
= LocalData[LocalIndex * 2 + 0] >> SIXTEENBITSHIFTFACTOR;
((signed short*)Buffer)[Scan * 2 + 1]
= LocalData[LocalIndex * 2 + 1] >> SIXTEENBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
else
{
/* stereo, 8-bit, no loop */
PRNGCHK(Buffer,Buffer,sizeof(char) * Limit * 2);
while (Scan < Limit)
{
if (LocalIndex >= LocalEnd)
{
goto AllDonePoint;
}
((signed char*)Buffer)[Scan * 2 + 0]
= LocalData[LocalIndex * 2 + 0] >> EIGHTBITSHIFTFACTOR;
((signed char*)Buffer)[Scan * 2 + 1]
= LocalData[LocalIndex * 2 + 1] >> EIGHTBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
}
else
{
if (NumBits == eSample16bit)
{
/* mono, 16-bit, no loop */
PRNGCHK(Buffer,Buffer,sizeof(short) * Limit);
while (Scan < Limit)
{
if (LocalIndex >= LocalEnd)
{
goto AllDonePoint;
}
((signed short*)Buffer)[Scan]
= LocalData[LocalIndex] >> SIXTEENBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
else
{
/* mono, 8-bit, no loop */
PRNGCHK(Buffer,Buffer,sizeof(char) * Limit);
while (Scan < Limit)
{
if (LocalIndex >= LocalEnd)
{
goto AllDonePoint;
}
((signed char*)Buffer)[Scan]
= LocalData[LocalIndex] >> EIGHTBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
}
goto SubmitPoint;
/* skip this */
AllDonePoint:
/* end of channel, time to stop playing */
SubmitBuffer((char*)Buffer,Scan,NIL,NIL);
State = eWaiting;
return;
}
else
{
LocalEnd = LoopEnd; /* for loop, this is what the end is */
if (NumChannels == eSampleStereo)
{
if (NumBits == eSample16bit)
{
/* stereo, 16-bit, yes loop */
PRNGCHK(Buffer,Buffer,sizeof(short) * Limit * 2);
while (Scan < Limit)
{
if (LocalIndex == LocalEnd)
{
LocalIndex = LoopStart;
}
((signed short*)Buffer)[Scan * 2 + 0]
= LocalData[LocalIndex * 2 + 0] >> SIXTEENBITSHIFTFACTOR;
((signed short*)Buffer)[Scan * 2 + 1]
= LocalData[LocalIndex * 2 + 1] >> SIXTEENBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
else
{
/* stereo, 8-bit, yes loop */
PRNGCHK(Buffer,Buffer,sizeof(char) * Limit * 2);
while (Scan < Limit)
{
if (LocalIndex == LocalEnd)
{
LocalIndex = LoopStart;
}
((signed char*)Buffer)[Scan * 2 + 0]
= LocalData[LocalIndex * 2 + 0] >> EIGHTBITSHIFTFACTOR;
((signed char*)Buffer)[Scan * 2 + 1]
= LocalData[LocalIndex * 2 + 1] >> EIGHTBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
}
else
{
if (NumBits == eSample16bit)
{
/* mono, 16-bit, yes loop */
PRNGCHK(Buffer,Buffer,sizeof(short) * Limit);
while (Scan < Limit)
{
if (LocalIndex == LocalEnd)
{
LocalIndex = LoopStart;
}
((signed short*)Buffer)[Scan]
= LocalData[LocalIndex] >> SIXTEENBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
else
{
/* mono, 8-bit, yes loop */
PRNGCHK(Buffer,Buffer,sizeof(char) * Limit);
while (Scan < Limit)
{
if (LocalIndex == LocalEnd)
{
LocalIndex = LoopStart;
}
((signed char*)Buffer)[Scan]
= LocalData[LocalIndex] >> EIGHTBITSHIFTFACTOR;
LocalIndex += 1;
Scan += 1;
}
}
}
}
/* play the data and write changed values out */
SubmitPoint:
SubmitBuffer((char*)Buffer,Limit,NIL,NIL);
CurrentIndex = LocalIndex;
}
void SampleTestBreakLoop(void)
{
ERROR(State != eLoopPlay,PRERR(ForceAbort,
"SampleTestBreakLoop: cancelling loop but it isn't looping"));
State = eNoLoopPlay;
}
SampleTestErrors SampleTestDidErrorOccur(void)
{
return ErrorOccurred;
}
void SampleTestPlayCleanup(void)
{
ERROR(State == eNoPlay,PRERR(ForceAbort,
"SampleTestPlayCleanup: nothing is playing"));
CloseSoundChannel(NIL,NIL);
State = eNoPlay;
}
MyBoolean SampleTestIsItLooping(void)
{
return State == eLoopPlay;
}
MyBoolean SampleTestIsWaitingForCleanup(void)
{
return State == eWaiting;
}